package myJs

import myJs.Implicits._
import myJs.Utils.{dataFileName, dataRow, dataValue, layer}
import myJs.myPkg._
import myJs.myPkg.jquery._
import org.scalajs.dom.ext.Ajax
import org.scalajs.dom.{Element, document}
import scalatags.Text.all._
import shared.VarTool

import scala.collection.immutable.SeqMap
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.scalajs.js
import scala.scalajs.js.Dynamic.{global => g}
import scala.scalajs.js.JSON
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
import scala.scalajs.js.JSConverters._
import myJs.myPkg.bootstrap.Bootstrap.default._
import myJs.tool.Tool

/**
 * Created by yz on 6/5/2021
 */
@JSExportTopLevel("Proportion")
object Proportion {

  val formId = "form"
  val bloodImageId = "bloodImage"
  val tissueImageId = "tissueImage"
  val tableId = "table"
  val modalId = "modal"
  val bloodKind = "blood"
  val tissueKind = "tissue"

  @JSExport("init")
  def init = {
    //    refreshPercentImage
    registerEvent
    initTable()
    refreshDataset.map { x =>
      refreshSample
      refreshTable
      refreshImage
    }

  }

  def tbFmt(columnName: String): js.Function = (v: js.Any, row: js.Dictionary[js.Any]) => {
    columnName match {
      case "RBC" =>
        a(href := "javascript:;", dataRow := s"${JSON.stringify(row)}", `class` := "myBlood",
          img(src := "/assets/images/blood_detail.png", cls := "runningImage", height := 20)
        )
      case "Adipose_Tissue" =>
        a(href := "javascript:;", dataRow := s"${JSON.stringify(row)}", `class` := "myTissue",
          img(src := "/assets/images/tissue_detail.png", cls := "runningImage", height := 20)
        )
      case _ => v
    }
  }

  def expStyle(columnName: String): js.Function = (v: js.Any, row: js.Dictionary[Any]) => columnName match {
    case _ => v
  }

  def initTable(tableJq: JQuery = $(s"#${tableId}")) = {
    val map = SeqMap("sample" -> "Sample", "type" -> "Sample type",
      "cohort" -> "Cohort",
      "Adipose_Tissue" -> "Tissue cells", "RBC" -> "Blood cells")
    val columnNames = map.keyList
    val columns = columnNames.map { columnName =>
      val title = map.getOrElse(columnName, columnName)
      val fmt = tbFmt(columnName)
      val style = expStyle(columnName)
      val basicOptions = ColumnOptions.field(columnName).title(title).titleTooltip(title).sortable(true).formatter(fmt).cellStyle(style)
      columnName match {
        case x if List("size", "uploadTime", "fileName", "comment", "tags").contains(x) => basicOptions.
          sortable(false).operateable(true)
        case _ => basicOptions
      }
    }
    val exportOptions = ExportOptions.fileName("data")
    val options = TableOptions.columns(columns.toJSArray).searchOnButton(false).filterControl(false).
      exportOptions(exportOptions).exportTypes(js.Array("csv")).showExport(true).exportDataType("all")
    tableJq.bootstrapTable(options)

    $(s"li[data-type='csv']").off("click")
    $(s"li[data-type='csv'] a").attr("href", "javascript:;")

  }

  def refreshDataset = {
    val url = g.jsRoutes.controllers.CellController.getAllDataset().url.toString
    Ajax.get(url = s"${url}").map { xhr =>
      val data = JSON.parse(xhr.responseText).toJArS
      val array = ("" +: data).map { v =>
        js.Dictionary("text" -> v, "id" -> v)
      }
      val singleOptions = Select2Options.multiple(false).allowClear(true).placeholder("click to choose").dictData(array)
      Tool.getInputByName("kind").select2(singleOptions)
      //      Tool.getInputByName("kind").select2Val(js.Array("HCC"))
    }
  }

  def refreshPercentImage = {
    Tool.useLoadingF() { () =>
      refreshPercentImageF
    }
  }

  def refreshPercentImageF = {
    val url = g.jsRoutes.controllers.CellController.getPercentImage().url.toString
    Ajax.get(url = s"${url}").map { xhr =>
      val rs = xhr.responseText.toJDJAn
      val valid = rs("valid").toB
      if (valid) {
        val bloodBase64 = rs("bloodBase64")
        $(s"#${bloodImageId}").attr("src", s"data:image/png;base64,${bloodBase64}")
        $(s"#${bloodImageId}").attr(Tool.dataBasicType, s"pdf")
        $(s"#${bloodImageId}").parents(".myCharts").findInputByName("pdfBase64").
          `val`(rs("bloodPdfBase64").toString)
        val tissueBase64 = rs("tissueBase64")
        $(s"#${tissueImageId}").attr("src", s"data:image/png;base64,${tissueBase64}")
        $(s"#${tissueImageId}").attr(Tool.dataBasicType, s"pdf")
        $(s"#${tissueImageId}").parents(".myCharts").findInputByName("pdfBase64").
          `val`(rs("tissuePdfBase64").toString)
      } else {
        Swal.swal(SwalOptions.title("Error").text(rs("message")).`type`("error"))
      }
    }
  }

  def registerEvent = {
    $(document.body).on("click", s".myRun", "", (y: Element) => {
      refreshImage
    })
    $(document.body).on("click", s".myBlood", "", (y: Element) => {
      val dict = $(y).dataRow.toJDS
      refreshDetail(dict, bloodKind)
    })
    $(document.body).on("click", s".myTissue", "", (y: Element) => {
      val dict = $(y).dataRow.toJDS
      refreshDetail(dict, tissueKind)
    })
    $(document.body).on("change", s".myKind", "", (y: Element) => {
      refreshSample
    })
    $(document.body).on("click", s".mySample", "", (y: Element) => {
      val value = $(y).dataValue
      Tool.getInputByName("sample").select2Val(value)
      refreshImage
    })

  }

  def refreshSample = {
    val url = g.jsRoutes.controllers.CellController.getAllSample().url.toString
    val formData = $(s"#form").serialize()
    Ajax.post(url = s"${url}", data = formData, headers = Map("Content-Type" -> "application/x-www-form-urlencoded")).map { xhr =>
      val data = JSON.parse(xhr.responseText).toJArS
      val array = ("" +: data).map { v =>
        js.Dictionary("text" -> v, "id" -> v)
      }
      val singleOptions = Select2Options.multiple(false).allowClear(true).placeholder("click to choose").dictData(array)
      Tool.getInputByName("sample").select2(singleOptions)
      //      Tool.getInputByName("kind").select2Val(js.Array("HCC"))
    }
  }

  def refreshDetailTable(dict: js.Dictionary[String], kind: String) = {
    case class TmpData(columnNames: List[String], color: String)
    val bloodColumnNames =
      List("RBC", "Platelet", "CD8_naive", "CD8_CM", "CD8_EM", "CD8_TE", "MAIT", "TFH", "Treg", "Th1", "Th17", "Th2", "CD4_naive", "B_naive", "Plasmablasts", "NK", "Neutrophils", "Basophils", "CD4_TE", "B_Memory", "DCs", "Monocytes", "T_gd")
    val tissueColumnNames = List("Adipose.Tissue", "Bladder", "Brain", "Colon", "Esophagus", "Heart", "Kidney", "Liver",
      "Lung", "Muscle", "Nerve", "Pancreas", "Pituitary", "Skin", "Small.Intestine", "Stomach")
    val data = kind match {
      case `bloodKind` => TmpData(bloodColumnNames, "#5E738B")
      case `tissueKind` => TmpData(tissueColumnNames, "#5E738B")
    }
    val cells = data.columnNames
    val first1Height = 30
    val html = cells.map { name =>
      val fieldName = name.replaceAll("\\.", "_")
      val url = g.jsRoutes.controllers.CellController.detailInfo().url.toString
      val v = dict(fieldName)
      val nameA = a(`class` := "myA", href := s"${url}?id=${name}", target := "_blank", name)
      div(cls := "form-group", marginRight := 15, height := 80, marginBottom := 20,
        table(cls := "table table-bordered detailTable", width := 120,
          tr(height := first1Height, maxHeight := first1Height, minHeight := first1Height, `class` := "myTr",
            td(`class` := "myTd",
              nameA,
              fontWeight := "bold", backgroundColor := data.color, paddingTop := 3, paddingBottom := 3)
          ),
          tr(height := first1Height, maxHeight := first1Height, minHeight := first1Height,
            td(
              v
            )
          ),
        )
      )
    }.mkString("&nbsp;")
    $(s"#${modalId} #detailData").html(html)
    jQuery(s"#${modalId}").modal("show")
  }

  def getDetailImg(dict: js.Dictionary[String], kind: String) = {
    val url = g.jsRoutes.controllers.CellController.getImage().url.toString
    val formData = $(s"#form").serialize()
    val sample = dict("sample")
    Ajax.post(url = s"${url}", data = s"${formData}&sample=${sample}",
      headers = Map("Content-Type" -> "application/x-www-form-urlencoded")).map { xhr =>
      val rs = xhr.responseText.toJDJAn
      val valid = rs("valid").toB
      if (valid) {
        val bloodBase64 = rs("bloodBase64")
        val bloodImageJq = $(s"#${modalId} #${VarTool.bloodKind} img")
        bloodImageJq.attr("src", s"data:image/png;base64,${bloodBase64}")
        bloodImageJq.attr(Tool.dataBasicType, s"pdf")
        bloodImageJq.parents(".myCharts").findInputByName("pdfBase64").
          `val`(rs("bloodPdfBase64").toString)
        val tissueBase64 = rs("tissueBase64")
        val tissueImageJq = $(s"#${modalId} #${VarTool.tissueKind} img")
        tissueImageJq.attr("src", s"data:image/png;base64,${tissueBase64}")
        tissueImageJq.attr(Tool.dataBasicType, s"pdf")
        tissueImageJq.parents(".myCharts").findInputByName("pdfBase64").
          `val`(rs("tissuePdfBase64").toString)
      } else {
        Swal.swal(SwalOptions.title("Error").text(rs("message")).`type`("error"))
      }
      valid
    }
  }

  def refreshDetailImg(dict: js.Dictionary[String], kind: String) = {
    val beforeSample = $("#lblAddTitle").text().trim.replaceAll(".*\\(", "").init
    val sample = dict("sample")
    val f = if (beforeSample == sample) {
      Future {
        true
      }
    } else {
      getDetailImg(dict, kind)
    }
    f.map { valid =>
      if (valid) {
        val bloodImageJq = $(s"#${modalId} #${VarTool.bloodKind} img")
        val tissueImageJq = $(s"#${modalId} #${VarTool.tissueKind} img")
        kind match {
          case VarTool.tissueKind =>
            tissueImageJq.parents(".myCharts").show()
            bloodImageJq.parents(".myCharts").hide()
          case VarTool.bloodKind =>
            bloodImageJq.parents(".myCharts").show()
            tissueImageJq.parents(".myCharts").hide()
        }
      }
      valid
    }


  }

  def refreshDetail(dict: js.Dictionary[String], kind: String) = {
    Tool.useLoadingF() { () =>
      refreshDetailImg(dict, kind).map { valid =>
        if (valid) {
          kind match {
            case VarTool.tissueKind => $("#lblAddTitle").text(s"Tissue cells(${dict("sample")})")
            case VarTool.bloodKind => $("#lblAddTitle").text(s"Blood cells(${dict("sample")})")
          }
          refreshDetailTable(dict, kind)
        }
      }
    }

  }

  def refreshImage = {
    Tool.useLoadingF() { () =>
      refreshTable
      refreshImageF
    }
  }

  def refreshTable = {
    val url = g.jsRoutes.controllers.CellController.getSelectedDataset().url.toString
    val formData = $(s"#form").serialize()
    Ajax.post(url = s"${url}", data = formData,
      headers = Map("Content-Type" -> "application/x-www-form-urlencoded")).map { xhr =>
      val data = xhr.responseText.toJArJDS
      $(s"#${tableId}").bootstrapTable("load", data)
    }
  }

  def refreshImageF = {
    val url = g.jsRoutes.controllers.CellController.getImage().url.toString
    val formData = $(s"#form").serialize()
    Ajax.post(url = s"${url}", data = s"${formData}",
      headers = Map("Content-Type" -> "application/x-www-form-urlencoded")).map { xhr =>
      val rs = xhr.responseText.toJDJAn
      val valid = rs("valid").toB
      if (valid) {
        val downloadUrl = g.jsRoutes.controllers.CellController.downloadProportionPlotData().url.toString
        val idStr = Tool.getInputByName("kind").myVal
        $(s"#${VarTool.tissueKind} a").attr("href",
          s"${downloadUrl}?kind=${VarTool.tissueKind}&id=${idStr}")
        $(s"#${VarTool.bloodKind} a").attr("href",
          s"${downloadUrl}?kind=${VarTool.bloodKind}&id=${idStr}")
        val bloodBase64 = rs("bloodBase64")
        $(s"#${bloodImageId}").attr("src", s"data:image/png;base64,${bloodBase64}")
        $(s"#${bloodImageId}").attr(Tool.dataBasicType, s"pdf")
        $(s"#${bloodImageId}").parents(".myCharts").findInputByName("pdfBase64").
          `val`(rs("bloodPdfBase64").toString)
        val tissueBase64 = rs("tissueBase64")
        $(s"#${tissueImageId}").attr("src", s"data:image/png;base64,${tissueBase64}")
        $(s"#${tissueImageId}").attr(Tool.dataBasicType, s"pdf")
        $(s"#${tissueImageId}").parents(".myCharts").findInputByName("pdfBase64").
          `val`(rs("tissuePdfBase64").toString)
        val tableDownloadUrl = g.jsRoutes.controllers.CellController.downloadProportionBrowseData().url.toString
        val hrefStr = if (idStr.nonEmpty) {
          s"${tableDownloadUrl}?id=${idStr}"
        } else "javascript:;"
        $(s"li[data-type='csv'] a").attr("href", hrefStr)
      } else {
        Swal.swal(SwalOptions.title("Error").text(rs("message")).`type`("error"))
      }
    }
  }


}
